home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Resources / Online / Term / Extras / Source / term-source.lha / SaveWindow.c < prev    next >
C/C++ Source or Header  |  1996-10-20  |  16KB  |  837 lines

  1. /*
  2. **    SaveWindow.c
  3. **
  4. **    Support routines for saving IFF-ILBM files
  5. **
  6. **    Copyright © 1990-1996 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. **
  9. **    :ts=4
  10. */
  11.  
  12. #ifndef _GLOBAL_H
  13. #include "Global.h"
  14. #endif
  15.  
  16.     /* Current compression mode. */
  17.  
  18. #define DUMP        0
  19. #define RUN            1
  20.  
  21.     /* ByteRun compression data. */
  22.  
  23. #define MINRUN        3
  24. #define MAXRUN        128
  25. #define MAXDAT        128
  26.  
  27.     /* Local packer data. */
  28.  
  29. STATIC BYTE Buffer[MAXDAT + 1];
  30. STATIC LONG PackedBytes;
  31.  
  32.     /* PutDump(PLANEPTR Destination,LONG Count):
  33.      *
  34.      *    Output a byte dump.
  35.      */
  36.  
  37. STATIC PLANEPTR
  38. PutDump(PLANEPTR Destination,LONG Count)
  39. {
  40.     PLANEPTR Source = Buffer;
  41.  
  42.     *Destination++ = Count - 1;
  43.  
  44.     PackedBytes += Count + 1;
  45.  
  46.     while(Count--)
  47.         *Destination++ = *Source++;
  48.  
  49.     return(Destination);
  50. }
  51.  
  52.     /* PutRun(PLANEPTR Destination,LONG Count,WORD Char):
  53.      *
  54.      *    Output a byte run.
  55.      */
  56.  
  57. STATIC PLANEPTR
  58. PutRun(PLANEPTR Destination,LONG Count,WORD Char)
  59. {
  60.     *Destination++ = -(Count - 1);
  61.     *Destination++ = Char;
  62.  
  63.     PackedBytes += 2;
  64.  
  65.     return(Destination);
  66. }
  67.  
  68.     /* PackRow(PLANEPTR *SourcePtr,PLANEPTR Destination,LONG RowSize):
  69.      *
  70.      *    Pack a row of bitmap data using ByteRun compression,
  71.      *    based on the original "EA IFF 85" pack.c example code.
  72.      */
  73.  
  74. STATIC LONG
  75. PackRow(PLANEPTR *SourcePtr,PLANEPTR Destination,LONG RowSize)
  76. {
  77.     PLANEPTR Source;
  78.     LONG Buffered,RunStart;
  79.     LONG Mode,LastChar,Char;
  80.  
  81.     Source        = *SourcePtr;
  82.     Buffered    = 1,
  83.     RunStart    = 0;
  84.     Mode        = DUMP;
  85.  
  86.     PackedBytes = 0;
  87.  
  88.     Buffer[0] = LastChar = Char = *Source++;
  89.  
  90.     RowSize--;
  91.  
  92.     while(RowSize--)
  93.     {
  94.         Buffer[Buffered++] = Char = *Source++;
  95.  
  96.         if(Mode)
  97.         {
  98.             if((Char != LastChar) || (Buffered - RunStart > MAXRUN))
  99.             {
  100.                 Destination    = PutRun(Destination,Buffered - 1 - RunStart,LastChar);
  101.                 Buffer[0]    = Char;
  102.                 Buffered    = 1;
  103.                 RunStart    = 0;
  104.                 Mode        = DUMP;
  105.             }
  106.         }
  107.         else
  108.         {
  109.             if(Buffered > MAXDAT)
  110.             {
  111.                 Destination    = PutDump(Destination,Buffered - 1);
  112.                 Buffer[0]    = Char;
  113.                 Buffered    = 1;
  114.                 RunStart    = 0;
  115.             }
  116.             else
  117.             {
  118.                 if(Char == LastChar)
  119.                 {
  120.                     if(Buffered - RunStart >= MINRUN)
  121.                     {
  122.                         if(RunStart)
  123.                             Destination = PutDump(Destination,RunStart);
  124.  
  125.                         Mode = RUN;
  126.                     }
  127.                     else
  128.                     {
  129.                         if(!RunStart)
  130.                             Mode = RUN;
  131.                     }
  132.                 }
  133.                 else
  134.                     RunStart = Buffered - 1;
  135.             }
  136.         }
  137.  
  138.         LastChar = Char;
  139.     }
  140.  
  141.     if(Mode)
  142.         PutRun(Destination,Buffered - RunStart,LastChar);
  143.     else
  144.         PutDump(Destination,Buffered);
  145.  
  146.     *SourcePtr = Source;
  147.  
  148.     return(PackedBytes);
  149. }
  150.  
  151.     /* PutANNO(struct IFFHandle *Handle):
  152.      *
  153.      *    Output `ANNO' chunk.
  154.      */
  155.  
  156. STATIC BOOL
  157. PutANNO(struct IFFHandle *Handle)
  158. {
  159.     LONG Len;
  160.     LONG Error;
  161.  
  162.     Len = strlen(&VersTag[1]);
  163.  
  164.         /* Push the `ANNO' chunk on the stack. */
  165.  
  166.     if(!(Error = PushChunk(Handle,0,ID_ANNO,Len)))
  167.     {
  168.             /* Write the creator string. */
  169.  
  170.         if(WriteChunkBytes(Handle,&VersTag[1],Len) == Len)
  171.         {
  172.                 /* Pop the `ANNO' chunk. */
  173.  
  174.             if(!(Error = PopChunk(Handle)))
  175.                 return(TRUE);
  176.         }
  177.         else
  178.             Error = IoErr();
  179.     }
  180.  
  181.     SetIoErr(Error);
  182.  
  183.     return(FALSE);
  184. }
  185.  
  186.     /* PutBMHD():
  187.      *
  188.      *    Output `BMHD' chunk.
  189.      */
  190.  
  191. STATIC BOOL
  192. PutBMHD(struct IFFHandle *Handle,struct Window *Window,UBYTE Compression,LONG Left,LONG Top,LONG Width,LONG Height)
  193. {
  194.     struct DisplayInfo DisplayInfo;
  195.     LONG Error;
  196.  
  197.         /* Get the display aspect ratio. */
  198.  
  199.     if(GetDisplayInfoData(NULL,(APTR)&DisplayInfo,sizeof(struct DisplayInfo),DTAG_DISP,GetVPModeID(&Window->WScreen->ViewPort)))
  200.     {
  201.         struct BitMapHeader Header;
  202.  
  203.             /* Fill in the bitmap header. */
  204.  
  205.         Header.bmh_Width        = Width;
  206.         Header.bmh_Height        = Height;
  207.         Header.bmh_PageWidth    = Window->WScreen->Width;
  208.         Header.bmh_PageHeight    = Window->WScreen->Height;
  209.         Header.bmh_Left            = Left;
  210.         Header.bmh_Top            = Top;
  211.         Header.bmh_Depth        = GetBitMapDepth(Window->WScreen->RastPort.BitMap);
  212.         Header.bmh_Masking        = mskNone;
  213.         Header.bmh_Compression    = Compression;
  214.         Header.bmh_Pad            = 0;
  215.         Header.bmh_Transparent    = 0;
  216.         Header.bmh_XAspect        = DisplayInfo.Resolution.x;
  217.         Header.bmh_YAspect        = DisplayInfo.Resolution.y;
  218.  
  219.             /* Push the `BMHD' chunk on the stack. */
  220.  
  221.         if(!(Error = PushChunk(Handle,0,ID_BMHD,sizeof(Header))))
  222.         {
  223.                 /* Write the bitmap header. */
  224.  
  225.             if(WriteChunkBytes(Handle,&Header,sizeof(Header)) == sizeof(Header))
  226.             {
  227.                     /* Pop the `BMHD' chunk. */
  228.  
  229.                 if(!(Error = PopChunk(Handle)))
  230.                     return(TRUE);
  231.             }
  232.             else
  233.                 Error = IoErr();
  234.         }
  235.     }
  236.     else
  237.         Error = ERROR_NO_FREE_STORE;
  238.  
  239.     if(Error)
  240.         SetIoErr(Error);
  241.  
  242.     return(FALSE);
  243. }
  244.  
  245.     /* PutCMAP(struct IFFHandle *Handle,struct ViewPort *VPort):
  246.      *
  247.      *    Output `CMAP' chunk, only 4-bit colour registers
  248.      *    are supported so far.
  249.      */
  250.  
  251. STATIC BOOL
  252. PutCMAP(struct IFFHandle *Handle,struct ViewPort *VPort)
  253. {
  254.     LONG Error;
  255.  
  256.         /* Push the `CMAP' chunk on the stack. */
  257.  
  258.     if(!(Error = PushChunk(Handle,0,ID_CMAP,3 * VPort->ColorMap->Count)))
  259.     {
  260.         struct ColorRegister Colour;
  261.         LONG i;
  262.  
  263.             /* Read and convert all the
  264.              * ColorMap entries (4 bit colour
  265.              * components only).
  266.              */
  267.  
  268.  
  269.         for(i = 0 ; i < VPort->ColorMap->Count ; i++)
  270.         {
  271.             if(Kick30)
  272.             {
  273.                 ULONG RGB[3];
  274.  
  275.                     /* Read colour value. */
  276.  
  277.                 GetRGB32(VPort->ColorMap,i,1,RGB);
  278.  
  279.                     /* Store the colour components. */
  280.  
  281.                 Colour.red        = RGB[0] >> 24;
  282.                 Colour.green    = RGB[1] >> 24;
  283.                 Colour.blue        = RGB[2] >> 24;
  284.             }
  285.             else
  286.             {
  287.                 ULONG Value;
  288.  
  289.                     /* Read colour value. */
  290.  
  291.                 Value = GetRGB4(VPort->ColorMap,i);
  292.  
  293.                     /* Split the value into components and store them. */
  294.  
  295.                 Colour.red        = ((Value >> 8) & 0xF) * 0x11;
  296.                 Colour.green    = ((Value >> 4) & 0xF) * 0x11;
  297.                 Colour.blue        = ((Value     ) & 0xF) * 0x11;
  298.             }
  299.  
  300.                 /* Write the colours. */
  301.  
  302.             if(WriteChunkBytes(Handle,&Colour,3) != 3)
  303.                 return(FALSE);
  304.         }
  305.  
  306.             /* Pop the `CMAP' chunk. */
  307.  
  308.         if(!(Error = PopChunk(Handle)))
  309.             return(TRUE);
  310.     }
  311.  
  312.     SetIoErr(Error);
  313.  
  314.     return(FALSE);
  315. }
  316.  
  317.     /* PutCAMG(struct IFFHandle *Handle,struct ViewPort *VPort):
  318.      *
  319.      *    Output `CAMG' chunk.
  320.      */
  321.  
  322. STATIC BOOL
  323. PutCAMG(struct IFFHandle *Handle,struct ViewPort *VPort)
  324. {
  325.     LONG Error;
  326.  
  327.     if(!(Error = PushChunk(Handle,0,ID_CAMG,sizeof(ULONG))))
  328.     {
  329.         ULONG ViewModes = GetVPModeID(VPort);
  330.  
  331.         if(WriteChunkBytes(Handle,&ViewModes,sizeof(ULONG)) == sizeof(ULONG))
  332.         {
  333.             if(!(Error = PopChunk(Handle)))
  334.                 return(TRUE);
  335.         }
  336.         else
  337.             Error = IoErr();
  338.     }
  339.  
  340.     if(Error)
  341.         SetIoErr(Error);
  342.  
  343.     return(FALSE);
  344. }
  345.  
  346.     /* PutBODY(struct IFFHandle *Handle)
  347.      *
  348.      *    Output `BODY' chunk.
  349.      */
  350.  
  351. STATIC BOOL
  352. PutBODY(struct IFFHandle *Handle,struct BitMap *BitMap,UBYTE Compression)
  353. {
  354.     PLANEPTR *Planes;
  355.     BOOL Success;
  356.     LONG Error;
  357.  
  358.     Success = FALSE;
  359.  
  360.         /* Allocate temporary bitplane pointers. */
  361.  
  362.     if(Planes = (PLANEPTR *)AllocVecPooled(BitMap->Depth * sizeof(PLANEPTR *),MEMF_ANY | MEMF_CLEAR))
  363.     {
  364.         LONG i;
  365.  
  366.             /* Copy the bitplane pointers. */
  367.  
  368.         for(i = 0 ; i < BitMap->Depth ; i++)
  369.             Planes[i] = BitMap->Planes[i];
  370.  
  371.             /* Are we to compress the data? */
  372.  
  373.         if(Compression == cmpByteRun1)
  374.         {
  375.             PLANEPTR PackBuffer;
  376.  
  377.                 /* Allocate line compression buffer. */
  378.  
  379.             if(PackBuffer = (PLANEPTR)AllocVecPooled(BitMap->BytesPerRow * 2,MEMF_ANY))
  380.             {
  381.                     /* Push the `BODY' chunk on the stack. */
  382.  
  383.                 if(!(Error = PushChunk(Handle,0,ID_BODY,IFFSIZE_UNKNOWN)))
  384.                 {
  385.                     LONG PackedBytes,j;
  386.  
  387.                         /* So far, we are quite successful,
  388.                          * any write access to fail will
  389.                          * cause `Success' to drop to FALSE.
  390.                          */
  391.  
  392.                     Success = TRUE;
  393.  
  394.                         /* Compress all the rows. */
  395.  
  396.                     for(i = 0 ; Success && i < BitMap->Rows ; i++)
  397.                     {
  398.                             /* Compress all the planes. */
  399.  
  400.                         for(j = 0 ; Success && j < BitMap->Depth ; j++)
  401.                         {
  402.                                 /* Do the compression. */
  403.  
  404.                             PackedBytes = PackRow(&Planes[j],PackBuffer,BitMap->BytesPerRow);
  405.  
  406.                                 /* Write the compressed data. */
  407.  
  408.                             if(WriteChunkBytes(Handle,PackBuffer,PackedBytes) != PackedBytes)
  409.                             {
  410.                                 Error = IoErr();
  411.  
  412.                                 Success = FALSE;
  413.                             }
  414.                         }
  415.                     }
  416.  
  417.                         /* Pop the `BODY' chunk. */
  418.  
  419.                     if(Success)
  420.                     {
  421.                         if(Error = PopChunk(Handle))
  422.                             Success = FALSE;
  423.                     }
  424.                 }
  425.  
  426.                     /* Free the line compression buffer. */
  427.  
  428.                 FreeVecPooled(PackBuffer);
  429.             }
  430.             else
  431.                 Error = ERROR_NO_FREE_STORE;
  432.         }
  433.         else
  434.         {
  435.                 /* Push the `BODY' chunk on the stack. */
  436.  
  437.             if(!(Error = PushChunk(Handle,0,ID_BODY,IFFSIZE_UNKNOWN)))
  438.             {
  439.                 LONG j;
  440.  
  441.                     /* So far, we are quite successful,
  442.                      * any write access to fail will
  443.                      * cause `Success' to drop to FALSE.
  444.                      */
  445.  
  446.                 Success = TRUE;
  447.  
  448.                     /* Compress all the rows. */
  449.  
  450.                 for(i = 0 ; Success && i < BitMap->Rows ; i++)
  451.                 {
  452.                         /* Compress all the planes. */
  453.  
  454.                     for(j = 0 ; Success && j < BitMap->Depth ; j++)
  455.                     {
  456.                             /* Write the row. */
  457.  
  458.                         if(WriteChunkBytes(Handle,Planes[j],BitMap->BytesPerRow) != BitMap->BytesPerRow)
  459.                         {
  460.                             Error = IoErr();
  461.  
  462.                             Success = FALSE;
  463.                         }
  464.                         else
  465.                             Planes[j] += BitMap->BytesPerRow;
  466.                     }
  467.                 }
  468.  
  469.                     /* Pop the `BODY' chunk. */
  470.  
  471.                 if(Success)
  472.                 {
  473.                     if(Error = PopChunk(Handle))
  474.                         Success = FALSE;
  475.                 }
  476.             }
  477.         }
  478.  
  479.             /* Free the temporary bitplane pointers. */
  480.  
  481.         FreeVecPooled(Planes);
  482.     }
  483.     else
  484.         Error = ERROR_NO_FREE_STORE;
  485.  
  486.     if(Error)
  487.         SetIoErr(Error);
  488.  
  489.         /* Return the result. */
  490.  
  491.     return(Success);
  492. }
  493.  
  494.     /* SaveWindow(STRPTR Name,struct Window *Window):
  495.      *
  496.      *    Save the contents of a window to a file.
  497.      */
  498.  
  499. BOOL
  500. SaveWindow(STRPTR Name,struct Window *Window)
  501. {
  502.     BOOL NewFile;
  503.     LONG Error;
  504.  
  505.     NewFile    = FALSE,
  506.     Error    = 0;
  507.  
  508.         /* Datatypes available? */
  509.  
  510.     if(DataTypesBase)
  511.     {
  512.         struct BitMap *BitMap;
  513.         struct Screen *Screen;
  514.         LONG Left,Top,Width,Height;
  515.         Object *Picture;
  516.  
  517.         Screen = Window->WScreen;
  518.         Picture = NULL;
  519.  
  520.             /* Keep these handy */
  521.  
  522.         Left    = Window->LeftEdge    + Window->BorderLeft;
  523.         Top        = Window->TopEdge    + Window->BorderTop;
  524.         Width    = Window->Width        - (Window->BorderLeft + Window->BorderRight);
  525.         Height    = Window->Height    - (Window->BorderTop + Window->BorderBottom);
  526.  
  527.         if(!StatusWindow)
  528.             Height -= StatusDisplayHeight;
  529.  
  530.             /* This is where the window contents will go */
  531.  
  532.         if(BitMap = AllocBitMap(Width,Height,GetBitMapAttr(Window->RPort->BitMap,BMA_DEPTH),NULL,Window->RPort->BitMap))
  533.         {
  534.             struct RastPort RPort;
  535.             LONG NumColours;
  536.  
  537.                 /* Provide temporary storage */
  538.  
  539.             InitRastPort(&RPort);
  540.  
  541.             RPort.BitMap = BitMap;
  542.  
  543.                 /* Copy the window contents */
  544.  
  545.             ClipBlit(Window->RPort,Window->BorderLeft,Window->BorderTop,&RPort,0,0,Width,Height,MINTERM_COPY);
  546.  
  547.                 /* Wait until all data is transferred */
  548.  
  549.             WaitBlit();
  550.  
  551.                 /* Get the number of colours available on this screen */
  552.  
  553.             NumColours = Screen->ViewPort.ColorMap->Count;
  554.  
  555.                 /* Create a picture object */
  556.  
  557.             if(Picture = NewDTObject("term image",
  558.                 DTA_SourceType,    DTST_RAM,
  559.                 DTA_GroupID,    GID_PICTURE,
  560.                 PDTA_NumColors,    NumColours,
  561.                 PDTA_BitMap,    BitMap,
  562.                 PDTA_ModeID,    GetVPModeID(&Screen->ViewPort),
  563.             TAG_DONE))
  564.             {
  565.                 struct ColorRegister *ColourMap;
  566.                 struct BitMapHeader *Header;
  567.                 ULONG *Colours;
  568.  
  569.                     /* Get the internal data arrays */
  570.  
  571.                 if(GetDTAttrs(Picture,
  572.                     PDTA_BitMapHeader,        &Header,
  573.                     PDTA_ColorRegisters,    &ColourMap,
  574.                     PDTA_CRegs,                &Colours,
  575.                 TAG_DONE) == 3)
  576.                 {
  577.                     LONG i;
  578.  
  579.                         /* Fill in the bitmap header */
  580.  
  581.                     Header->bmh_Left        = Left;
  582.                     Header->bmh_Top            = Top;
  583.                     Header->bmh_Width        = Width;
  584.                     Header->bmh_Height        = Height;
  585.                     Header->bmh_Depth        = GetBitMapAttr(BitMap,BMA_DEPTH);
  586.                     Header->bmh_PageWidth    = Screen->Width;
  587.                     Header->bmh_PageHeight    = Screen->Height;
  588.  
  589.                         /* Get the 32 colours */
  590.  
  591.                     GetRGB32(Screen->ViewPort.ColorMap,0,NumColours,Colours);
  592.  
  593.                         /* Get the 24 bit colours */
  594.  
  595.                     for(i = 0 ; i < NumColours ; i++)
  596.                     {
  597.                         ColourMap[i].red    = (UBYTE)(Colours[i * 3 + 0] >> 24);
  598.                         ColourMap[i].green    = (UBYTE)(Colours[i * 3 + 1] >> 24);
  599.                         ColourMap[i].blue    = (UBYTE)(Colours[i * 3 + 2] >> 24);
  600.                     }
  601.                 }
  602.                 else
  603.                 {
  604.                     Error = IoErr();
  605.  
  606.                     DisposeDTObject(Picture);
  607.  
  608.                     Picture = NULL;
  609.                 }
  610.             }
  611.             else
  612.                 Error = IoErr();
  613.         }
  614.         else
  615.             Error = ERROR_NO_FREE_STORE;
  616.  
  617.             /* Successful so far? */
  618.  
  619.         if(Picture)
  620.         {
  621.             BPTR FileHandle;
  622.  
  623.                 /* Open the output file */
  624.  
  625.             if(FileHandle = Open(Name,MODE_NEWFILE))
  626.             {
  627.                     /* Save the image */
  628.  
  629.                 if(!DoMethod(Picture,DTM_WRITE,NULL,FileHandle,DTWM_IFF,NULL))
  630.                 {
  631.                     Error = IoErr();
  632.  
  633.                     NewFile = TRUE;
  634.                 }
  635.  
  636.                 Close(FileHandle);
  637.             }
  638.             else
  639.                 Error = IoErr();
  640.  
  641.             DisposeDTObject(Picture);
  642.         }
  643.         else
  644.         {
  645.             if(BitMap)
  646.                 FreeBitMap(BitMap);
  647.         }
  648.     }
  649.     else
  650.     {
  651.         struct RastPort *RPort;
  652.         LONG Depth;
  653.  
  654.             /* Get the depth. */
  655.  
  656.         Depth = GetBitMapDepth(Window->WScreen->RastPort.BitMap);
  657.  
  658.         if(Depth > 8)
  659.         {
  660.             SetIoErr(ERROR_OBJECT_WRONG_TYPE);
  661.  
  662.             return(FALSE);
  663.         }
  664.  
  665.             /* Allocate a dummy rastport, we will need only
  666.              * to copy the contents of the window into the
  667.              * bitmap.
  668.              */
  669.  
  670.         if(RPort = (struct RastPort *)AllocVecPooled(sizeof(struct RastPort),MEMF_ANY))
  671.         {
  672.             struct BitMap *BitMap;
  673.  
  674.                 /* Initialize the rastport with defaults. */
  675.  
  676.             InitRastPort(RPort);
  677.  
  678.                 /* Allocate a bitmap. */
  679.  
  680.             if(BitMap = (struct BitMap *)AllocVecPooled(sizeof(struct BitMap),MEMF_ANY))
  681.             {
  682.                 LONG i,Left,Top,Width,Height;
  683.  
  684.                 Width    = Window->Width        - (Window->BorderLeft + Window->BorderRight);
  685.                 Height    = Window->Height    - (Window->BorderTop + Window->BorderBottom);
  686.                 Left    = Window->LeftEdge    + Window->BorderLeft;
  687.                 Top        = Window->TopEdge    + Window->BorderTop;
  688.  
  689.                 if(!StatusWindow)
  690.                     Height -= StatusDisplayHeight;
  691.  
  692.                     /* Put it into the rastport. */
  693.  
  694.                 RPort->BitMap = BitMap;
  695.  
  696.                     /* Initialize it with the window dimensions. */
  697.  
  698.                 InitBitMap(BitMap,Depth,Width,Height);
  699.  
  700.                     /* Allocate all the bitplanes necessary. */
  701.  
  702.                 for(i = 0 ; !Error && i < BitMap->Depth ; i++)
  703.                 {
  704.                     if(!(BitMap->Planes[i] = AllocRaster(Width,Height)))
  705.                         Error = ERROR_NO_FREE_STORE;
  706.                 }
  707.  
  708.                     /* Did we get all the planes we wanted? */
  709.  
  710.                 if(!Error)
  711.                 {
  712.                     struct IFFHandle *Handle;
  713.  
  714.                         /* Copy the window contents to the
  715.                          * local bitmap.
  716.                          */
  717.  
  718.                     ClipBlit(Window->RPort,Window->BorderLeft,Window->BorderTop,RPort,0,0,Width,Height,MINTERM_COPY);
  719.  
  720.                         /* Wait for the data to arrive. */
  721.  
  722.                     WaitBlit();
  723.  
  724.                         /* Allocate an iff handle. */
  725.  
  726.                     if(Handle = OpenIFFStream(Name,MODE_NEWFILE))
  727.                     {
  728.                         NewFile = TRUE;
  729.  
  730.                             /* Push parent chunk on the
  731.                              * stack.
  732.                              */
  733.  
  734.                         if(!(Error = PushChunk(Handle,ID_ILBM,ID_FORM,IFFSIZE_UNKNOWN)))
  735.                         {
  736.                                 /* Output all the chunk data. */
  737.  
  738.                             if(PutANNO(Handle))
  739.                             {
  740.                                 UBYTE Compression;
  741.  
  742.                                     /* Don't compress the bitmap if
  743.                                      * isn't really worth it.
  744.                                      */
  745.  
  746.                                 if(BitMap->BytesPerRow > 4)
  747.                                     Compression = cmpByteRun1;
  748.                                 else
  749.                                     Compression = cmpNone;
  750.  
  751.                                 if(PutBMHD(Handle,Window,Compression,Left,Top,Width,Height))
  752.                                 {
  753.                                     if(PutCMAP(Handle,&Window->WScreen->ViewPort))
  754.                                     {
  755.                                         if(PutCAMG(Handle,&Window->WScreen->ViewPort))
  756.                                         {
  757.                                             if(PutBODY(Handle,BitMap,Compression))
  758.                                             {
  759.                                                     /* Pop the parent chunk
  760.                                                      * from the stack.
  761.                                                      */
  762.  
  763.                                                 Error = PopChunk(Handle);
  764.                                             }
  765.                                             else
  766.                                                 Error = IoErr();
  767.                                         }
  768.                                         else
  769.                                             Error = IoErr();
  770.                                     }
  771.                                     else
  772.                                         Error = IoErr();
  773.                                 }
  774.                                 else
  775.                                     Error = IoErr();
  776.                             }
  777.                             else
  778.                                 Error = IoErr();
  779.                         }
  780.  
  781.                             /* Free the iff handle. */
  782.  
  783.                         CloseIFFStream(Handle);
  784.                     }
  785.                     else
  786.                         Error = IoErr();
  787.                 }
  788.                 else
  789.                     Error = ERROR_NO_FREE_STORE;
  790.  
  791.                     /* Free all bitplanes. */
  792.  
  793.                 for(i = 0 ; i < BitMap->Depth ; i++)
  794.                 {
  795.                     if(BitMap->Planes[i])
  796.                         FreeRaster(BitMap->Planes[i],Width,Height);
  797.                 }
  798.  
  799.                     /* Free the bitmap. */
  800.  
  801.                 FreeVecPooled(BitMap);
  802.             }
  803.             else
  804.                 Error = ERROR_NO_FREE_STORE;
  805.  
  806.                 /* Free the rastport. */
  807.  
  808.             FreeVecPooled(RPort);
  809.         }
  810.         else
  811.             Error = ERROR_NO_FREE_STORE;
  812.     }
  813.  
  814.         /* Did we get an error? */
  815.  
  816.     if(Error)
  817.     {
  818.         if(NewFile)
  819.             DeleteFile(Name);
  820.  
  821.         SetIoErr(Error);
  822.  
  823.         return(FALSE);
  824.     }
  825.     else
  826.     {
  827.             /* If successful, clear the `executable' bit. */
  828.  
  829.         AddProtection(Name,FIBF_EXECUTE);
  830.  
  831.         if(Config->MiscConfig->CreateIcons)
  832.             AddIcon(CaptureName,FILETYPE_PICTURE,TRUE);
  833.  
  834.         return(TRUE);
  835.     }
  836. }
  837.